package edu.stanford.bmir.protege.web.server.stkosutil.enricher;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.List;


import edu.stanford.bmir.protege.web.client.rpc.stkosutil.common.TripleData;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.common.UtilConstants;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.common.UtilEntityType;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.CandidateEntity;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.EnricherSource;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.EnrichmentOptions;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.SourceThesaurus;
import edu.stanford.bmir.protege.web.server.stkosutil.common.AppException;
import edu.stanford.bmir.protege.web.server.stkosutil.common.HttpClient;

public class KnowlegeBaseClient {
	private static KnowlegeBaseClient _instance = null;
	public static KnowlegeBaseClient getInstance(){
		if (_instance==null){
			_instance = new KnowlegeBaseClient();
		}
		return _instance;
	}
	//private String _baseServiceUrl = "http://10.1.72.107/ontologyservice/"; //内网IP
	private String _baseServiceUrl = "http://114.255.123.96/ontologyservice/"; //外网IP
	//private String _baseServiceUrl = "http://localhost:8080/ontologyservice/"; //本地IP
	public ArrayList<CandidateEntity> fetchCandidateChildClasses(String parentClassName, ArrayList<Long> thesaurusIdList) throws AppException {
		//http://localhost:8080/ontologyservice/mvccontroller?pEvent=FETCH_RELATED_TERMS&term=fruit
		String sThesaurusIdList = "";
		if (thesaurusIdList!=null && thesaurusIdList.size()>0){
			for (Long thesaurusId:thesaurusIdList){
				sThesaurusIdList += ((sThesaurusIdList.length()==0)?"":",")
						+ thesaurusId.longValue();
			}
		}
		String serviceUrl = _baseServiceUrl + "mvccontroller";
		Hashtable<String,String> hParameters = new Hashtable<String,String>();
		hParameters.put("pEvent","FETCH_RELATED_TERMS");
		hParameters.put("term",parentClassName);
		if (sThesaurusIdList.length()>0){
			hParameters.put("thesaurusIds", sThesaurusIdList);
		}
		String result = HttpClient.doPost(serviceUrl, hParameters);
		if (result.startsWith(HttpClient.FLAG_SUCCESS)){
			String childClassList = result.substring(HttpClient.FLAG_SUCCESS.length());
			ArrayList<CandidateEntity>  alCandidateEntityList = null;
			if (childClassList.length()>0){
				alCandidateEntityList = extractChildClasses(childClassList);
			}else{
				alCandidateEntityList = new ArrayList<CandidateEntity>();
			}
			return alCandidateEntityList;
        }else if (result.startsWith(HttpClient.FLAG_ERROR)){
            String errorMessage = result.substring(HttpClient.FLAG_ERROR.length());
            throw new AppException(errorMessage);
        }else{
        	return null;
        } 
	}
	private ArrayList<CandidateEntity> extractChildClasses(String childClassList){
		ArrayList<CandidateEntity> alCandidateEntityList = new ArrayList<CandidateEntity>(); 
		String[] aRecords = childClassList.split(HttpClient.RECORD_SEPARATOR);
		for (String record: aRecords){
			String[] aFields = record.split(HttpClient.FIELD_SEPARATOR);
			CandidateEntity entity = new CandidateEntity();
			entity.setEntityType(UtilEntityType.CLASS);
			entity.setBrowserText(aFields[0]);
			entity.setSourceLabel((aFields[2]==null)?"":aFields[2]);
			alCandidateEntityList.add(entity);
		}
		return alCandidateEntityList;
	}
	
	public List<SourceThesaurus> fetchSourceThesaurusList() throws AppException {
		//http://localhost:8080/ontologyservice/mvccontroller?pEvent=FETCH_RELATED_TERMS&term=fruit
		String serviceUrl = _baseServiceUrl + "mvccontroller";
		Hashtable<String,String> hParameters = new Hashtable<String,String>();
		hParameters.put("pEvent","FETCH_HIERARCHICAL_THESAURUS_LIST");
		String result = HttpClient.doPost(serviceUrl, hParameters);
		if (result.startsWith(HttpClient.FLAG_SUCCESS)){
			String thesaurusListText = result.substring(HttpClient.FLAG_SUCCESS.length());
			List<SourceThesaurus>  alThesaurusList = extractThesaurusList(thesaurusListText);
			return alThesaurusList;
        }else if (result.startsWith(HttpClient.FLAG_ERROR)){
            String errorMessage = result.substring(HttpClient.FLAG_ERROR.length());
            throw new AppException(errorMessage);
        }else{
        	return null;
        } 
	}
	private List<SourceThesaurus> extractThesaurusList(String thesaurusListText){
		ArrayList<SourceThesaurus> alThesaurusList = new ArrayList<SourceThesaurus>(); 
		String[] aRecords = thesaurusListText.split(HttpClient.RECORD_SEPARATOR);
		for (String record: aRecords){
			String[] aFields = record.split(HttpClient.FIELD_SEPARATOR);
			SourceThesaurus thesaurus = new SourceThesaurus();
			thesaurus.setThesaurusId(Long.parseLong(aFields[0]));
			thesaurus.setThesaurusAbbr(aFields[1]);
			thesaurus.setThesaurusName(aFields[2]);
			thesaurus.setDisplayName(thesaurus.getThesaurusName());
			alThesaurusList.add(thesaurus);
		}
		return alThesaurusList;
	}
	
	public List<TripleData> fetchTripleDataList(String subject, EnrichmentOptions options) throws AppException {
		//http://localhost:8080/ontologyservice/mvccontroller?pEvent=FETCH_TRIPLE_DATA_LIST&subject=oils&dataSourceType=2
		String serviceUrl = _baseServiceUrl + "mvccontroller";
		Hashtable<String,String> hParameters = new Hashtable<String,String>();
		hParameters.put("pEvent","FETCH_TRIPLE_DATA_LIST");
		hParameters.put("subject",subject);
		hParameters.put("dataSourceType",options.getSource() == EnricherSource.THESAURUS?"1":"2");
		if (options.getRefThesaurusID()!=UtilConstants.UNKNOWN_INT_VALUE){
			String sIdList = "";
			sIdList=options.getRefThesaurusID() + "";
			hParameters.put("thesaurusIds",sIdList);
		}
		
		String result = HttpClient.doPost(serviceUrl, hParameters);
		if (result.startsWith(HttpClient.FLAG_SUCCESS)){
			String tripleDataListText = result.substring(HttpClient.FLAG_SUCCESS.length());
			if (tripleDataListText.length()>0){
				List<TripleData> alTripleDataList = extractTripleDataList(tripleDataListText);
				return alTripleDataList;
			}else{
				return null;
			}
        }else if (result.startsWith(HttpClient.FLAG_ERROR)){
            String errorMessage = result.substring(HttpClient.FLAG_ERROR.length());
            throw new AppException(errorMessage);
        }else{
        	return null;
        } 
	}
	private List<TripleData> extractTripleDataList(String tripleDataListText){
		ArrayList<TripleData> alTripleDataList = new ArrayList<TripleData>(); 
		String[] aRecords = tripleDataListText.split(HttpClient.RECORD_SEPARATOR);
		for (String record: aRecords){
			String[] aFields = record.split(HttpClient.FIELD_SEPARATOR);
			TripleData tripleData = new TripleData();
			tripleData.setSubject(aFields[0]);
			tripleData.setPredicate(aFields[1]);
			tripleData.setObject(aFields[2]);
			alTripleDataList.add(tripleData);
		}
		return alTripleDataList;
	}
	
	public List<TripleData> fetchCandidateTripleList(String subject, EnrichmentOptions options) throws AppException {
		//http://localhost:8080/ontologyservice/mvccontroller?pEvent=FETCH_CANDIDATE_TRIPLE_LIST&subject=oils&dataSourceType=2&thesaurusIds=1,2,3
		String serviceUrl = _baseServiceUrl + "mvccontroller";
		Hashtable<String,String> hParameters = new Hashtable<String,String>();
		hParameters.put("pEvent","FETCH_CANDIDATE_TRIPLE_LIST");
		hParameters.put("subject",subject);
		hParameters.put("dataSourceType",options.getSource()==EnricherSource.THESAURUS?"1":"2");
		if (options.getRefThesaurusID()!=UtilConstants.UNKNOWN_INT_VALUE){
			String sIdList = "";
			sIdList = options.getRefThesaurusID() + "";
			hParameters.put("thesaurusIds",sIdList);
		}
		
		String result = HttpClient.doPost(serviceUrl, hParameters);
		if (result.startsWith(HttpClient.FLAG_SUCCESS)){
			String tripleDataListText = result.substring(HttpClient.FLAG_SUCCESS.length());
			if (tripleDataListText.length()>0){
				List<TripleData> alTripleDataList = extractTripleDataList2(tripleDataListText);
				return alTripleDataList;
			}else{
				return null;
			}
        }else if (result.startsWith(HttpClient.FLAG_ERROR)){
            String errorMessage = result.substring(HttpClient.FLAG_ERROR.length());
            throw new AppException(errorMessage);
        }else{
        	return null;
        } 
	}
	
	private List<TripleData> extractTripleDataList2(String tripleDataListText){
		ArrayList<TripleData> alTripleDataList = new ArrayList<TripleData>(); 
		String[] aRecords = tripleDataListText.split(HttpClient.RECORD_SEPARATOR);
		for (String record: aRecords){
			String[] aFields = record.split(HttpClient.FIELD_SEPARATOR);
			TripleData tripleData = new TripleData();
			tripleData.setSubject(aFields[0]);
			tripleData.setPredicate(aFields[1]);
			tripleData.setObject(aFields[2]);
			if (aFields.length==4){
				tripleData.setSourceName(aFields[3]);
			}else{
				tripleData.setSourceName("Document Triples");
			}
			alTripleDataList.add(tripleData);
		}
		return alTripleDataList;
	}
}
